﻿<template>
    <el-select :value="currentValue"
               :placeholder="placeholder"
               :clearable="clearable"
               :disabled="disabled"
               :multiple="multiple"
               :allow-create="allowCreate"
               :filterable="myFilterable"
               :no-match-text="noMatchText"
               :size="size"
               @filter-method="handlerFilterMethod"
               @input="handleInput"
               @change="handlerChange"
               @blur="handlerBlur">
        <slot>
            <el-option v-for="option in myOptions"
                       :key="option.value"
                       :label="option[myProps.label]"
                       :value="option[myProps.value].toString()"></el-option>
        </slot>
    </el-select>
</template>

<script>
export default {
  name: 'form-select',
  data () {
    return {
      currentValue: this.value === undefined || this.value === null
        ? '' : this.value,
      myOptions: [], // 选项数据
      beCreateOption: null
    }
  },
  props: {
    size: {
      type: String,
      default: ''
    },
    value: {
      type: [Number, String, Array]
    },
    placeholder: String,
    options: {
      type: [Array, Function, Object],
      required: true
    },
    disabled: Boolean,
    props: {
      type: Object,
      default () {
        return {
          children: 'options',
          label: 'label',
          value: 'value',
          disabled: 'disabled',
          parentNodeKey: 'ParentId'
        }
      }
    },
    valueType: {
      type: String,
      default: 'Number'
    },
    clearable: {
      type: Boolean,
      default: true
    },
    multiple: {
      type: Boolean,
      default: false
    },
    allowCreate: {
      type: Boolean,
      default: false
    },
    filterable: {
      type: Boolean,
      default: false
    },
    // 搜索条件无匹配时显示的文字，也可以使用slot="empty"设置
    noMatchText: {
      type: String
    }
  },
  watch: {
    value (newVal) {
      this.setCurrentValue(newVal)
    },
    options (newVal) {
      // 生成下拉菜单选项
      this.createMyOptions()

      let value = this.value

      if (!this.clearable &&
                    this.value == '' &&
                    Object.prototype.toString.call(newVal) == '[object Array]' &&
                    newVal.length > 0
      ) {
        value = newVal[0][this.myProps.value]
        this.handleInput(value)
      }
      this.setCurrentValue(value)
    }
  },
  computed: {
    // 是否启用搜索
    myFilterable () {
      return this.allowCreate || this.filterable
    },
    // 传入的props
    myProps () {
      var props = this.props || {}
      return {
        children: props.children || 'options',
        label: props.label || 'label',
        value: props.value || 'value',
        disabled: props.disabled || 'disabled',
        parentNodeKey: props.parentNodeKey || 'ParentId'
      }
    }
  },
  methods: {
    // 重新生成options
    createMyOptions () {
      let options = []

      options = this.$core.convertOptions({
        options: this.options,
        props: this.myProps
      })

      this.myOptions = options
      return

      let tempOptions = Object.prototype.toString.call(this.options) === '[object Function]' ? this.options() : this.options

      tempOptions.forEach((option) => {
        options.push({
          label: option[this.myProps.label],
          value: option[this.myProps.value],
          disabled: typeof option[this.myProps.disabled] === 'boolean'
            ? option[this.myProps.disabled] : false
        })
      })

      this.myOptions = options
    },
    // 设置当前值
    setCurrentValue (value) {
      value = value || this.value

      if (value === undefined || value === null) {
        value = ''
      }

      if (Object.prototype.toString.call(value) === '[object Number]') {
        value = value.toString()
      } else if (
        Object.prototype.toString.call(value) === '[object Array]'
      ) {
        for (var i = 0; i < value.length; i++) {
          value[i] = value[i].toString()
        }
      }

      this.currentValue = value
    },
    // 更新下拉框选择的值
    submitValue (value) {
      // 是否是需要添加的内容状态变量
      var isCreatedValue = Object.prototype.toString.call(value) != '[object Array]' && value != ''

      // 遍历选项，比对值是否是需要添加的
      this.myOptions.forEach((option) => {
        if (isCreatedValue == true) {
          if (
            option[this.myProps.value].toString() == value.toString()
          ) {
            // 如果匹配选项列表中的相同选项值
            isCreatedValue = false
          } else if (
            option[this.myProps.label].toString() ==
                            value.toString().trim()
          ) {
            // 如果匹配到选项列表中的相同选项文本
            value = option[this.myProps.value]

            isCreatedValue = false
          }
        }
      })

      if (isCreatedValue) {
        if (
          this.beCreateOption != null &&
                        value.toString().trim() !=
                        this.beCreateOption[this.myProps.label]
        ) {
          this.myOptions.remove(this.beCreateOption)
        }

        let option = {}
        option[this.myProps.value] = 0
        option[this.myProps.label] = value.toString().trim()

        this.beCreateOption = option

        this.myOptions.push(this.beCreateOption)

        value = this.beCreateOption[this.myProps.value]
      } else {
        this.myOptions.remove(this.beCreateOption)

        this.beCreateOption = null
      }

      this.setCurrentValue(value)

      if (this.allowCreate) {
        this.$emit('create-change', this.beCreateOption)
      }

      this.$emit('input', value)

      return value
    },
    handleInput (value) {
      this.submitValue(value)
    },
    // 选中值变化事件
    handlerChange (value) {
      value = this.submitValue(value)
      let rows = this.myOptions.filter(c => c[this.props.value] == value)

      let row = rows.length > 0 ? rows[0] : {}

      try {
        this.$emit('change', value, row)
      } catch (e) {}
    },
    // 失去交点事件
    handlerBlur (e) {
      if (this.allowCreate) {
        var value = e.target.value

        this.submitValue(value)
      }
    },
    handlerFilterMethod () {}
  },
  mounted () {
    this.createMyOptions()

    this.setCurrentValue()
  }
}
</script>

<style>
    /* 防止变短 */

    .el-select {
        display: block !important;
    }
    /* 滚动条显示  以及最大高度 */
    .el-scrollbar__wrap {
        overflow: auto !important;
    }
    .el-select-dropdown__wrap{
        max-height: 240px !important;
    }
    /* 下拉框地板间距样式 */
    .el-popper[x-placement^=bottom] {
        padding-bottom: 5px;
    }
</style>
